﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using Omnia.Infrastructure;
using System.Net;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using Omnia.Library;
using System.Windows.Input;
using System.Xml.Linq;
using Omnia.Library.Extensions;

namespace Omnia.ViewModels
{
    public class LanguageDownloadViewModel : ViewModelBase
    {
        #region Constructors
        WebClient client = new WebClient();

        WebClient resolveClient = new WebClient();

        public LanguageDownloadViewModel()
        {
            fetchedLanguages = new ObservableCollection<string>(SampleData);
            client.DownloadStringCompleted -= client_DownloadStringCompleted;
            client.DownloadStringCompleted += client_DownloadStringCompleted;

            client.DownloadProgressChanged -= client_DownloadProgressChanged;
            client.DownloadProgressChanged += client_DownloadProgressChanged;

            resolveClient.DownloadStringCompleted += resolveClient_DownloadStringCompleted;
            resolveClient.DownloadStringAsync(new Uri(ConstKeys.LanguageFetchUriString, UriKind.RelativeOrAbsolute));
        } 
        #endregion

        #region Method
        private void StartDownload()
        {
            if (!string.IsNullOrWhiteSpace(SelectedLanguage))
            {
                
                client.DownloadStringAsync(new Uri(string.Format("{0}/{1}.xaml", ConstKeys.LanguageUriString, SelectedLanguage), UriKind.RelativeOrAbsolute));
                RaisePropertyChanged(() => DownloadPanelVisibility);
                RaisePropertyChanged(() => ListVisibility);
            }
        }

        private void DeleteLanguagePackage()
        {
            using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
            {
                string filename = @"\Languages\" + SelectedExistLanguage + ".xaml";

                if (store.FileExists(filename))
                {
                    try
                    {
                        store.DeleteFile(filename);
                        RaisePropertyChanged(() => ExistsLanguageFile);
                    }
                    catch { }
                }
            }
        }

        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            DownloadedPercent = (e.BytesReceived * 100) / e.TotalBytesToReceive;
            DownloadedBytes = e.BytesReceived;
            TotalBytes = e.TotalBytesToReceive;
        }

        void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(e.Result);
                Stream stream = new MemoryStream(buffer);
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        string fileName = @"\Languages\" + SelectedLanguage + ".xaml";
                        if (store.FileExists(fileName))
                        {
                            store.DeleteFile(fileName);
                        }

                        using (IsolatedStorageFileStream fileStream = store.OpenFile(fileName, FileMode.OpenOrCreate, FileAccess.Write))
                        {
                            using (BinaryWriter writer = new BinaryWriter(fileStream))
                            {
                                writer.Write(reader.ReadBytes(Convert.ToInt32(stream.Length)));
                            }
                            fileStream.Close();
                            fileStream.Dispose();
                        }
                    }
                }

                if (MessageBox.Show("下载完成，是否设置为程序显示语言？", "", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    GlobalSettings.Language = SelectedExistLanguage;
                    RaisePropertyChanged(() => GlobalSettings);
                }
            }
            RaisePropertyChanged(() => ExistsLanguageFile);
            RaisePropertyChanged(() => DownloadPanelVisibility);
            RaisePropertyChanged(() => ListVisibility);
        }

        void resolveClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                byte[] buffer = Encoding.UTF8.GetBytes(e.Result);
                Stream stream = new MemoryStream(buffer);
                XDocument xDoc = XDocument.Load(stream);

                var items = from item in xDoc.Descendants("language")
                            select item.Value ;

                FetchedLanguages = new ObservableCollection<string>(items);
                BusyIndicatorVisibility = Visibility.Collapsed;
                RaisePropertyChanged(() => ListVisibility);
            }
            else
            {
                MessageBox.Show(e.Error.Message);
            }
        }

        #endregion

        #region Properties

        private long downloadedBytes = 0;
        public long DownloadedBytes
        {
            get { return downloadedBytes; }
            set
            {
                downloadedBytes = value;
                RaisePropertyChanged(() => DownloadedBytes);
            }
        }

        private long totalBytes = 0;
        public long TotalBytes
        {
            get { return totalBytes; }
            set
            {
                totalBytes = value;
                RaisePropertyChanged(() => TotalBytes);
            }
        }

        private double downloadedPercent = 0;
        public double DownloadedPercent
        {
            get { return downloadedPercent; }
            set
            {
                downloadedPercent = value;
                RaisePropertyChanged(() => DownloadedPercent);
            }
        }



        private string selectedLanguage;
        public string SelectedLanguage
        {
            get { return selectedLanguage; }
            set
            {
                selectedLanguage = value;
                RaisePropertyChanged(() => SelectedLanguage);
                RaisePropertyChanged(() => DownloadCommand);
            }
        }

        private string selectedExistLanguage;
        public string SelectedExistLanguage
        {
            get { return selectedExistLanguage; }
            set
            {
                selectedExistLanguage = value;
                RaisePropertyChanged(() => SelectedExistLanguage);
                RaisePropertyChanged(() => DeleteCommand);
                RaisePropertyChanged(() => SetLanguageCommand);
            }
        }


        private Visibility busyIndicatorVisibility = Visibility.Visible;
        public Visibility BusyIndicatorVisibility
        {
            get { return busyIndicatorVisibility; }
            set
            {
                busyIndicatorVisibility = value;
                RaisePropertyChanged(() => BusyIndicatorVisibility);
            }
        }

        public Visibility DownloadPanelVisibility
        {
            get { return client.IsBusy ? Visibility.Visible : Visibility.Collapsed; }
        }

        public Visibility ListVisibility
        {
            get
            {
                if (BusyIndicatorVisibility == Visibility.Visible)
                {
                    return Visibility.Collapsed;
                }
                return client.IsBusy ? Visibility.Collapsed : Visibility.Visible;
            }
        }

        private ObservableCollection<string> fetchedLanguages;
        public ObservableCollection<string> FetchedLanguages
        {
            get { return fetchedLanguages; }
            set
            {
                fetchedLanguages = value;
                RaisePropertyChanged(() => FetchedLanguages);
            }
        }


        public IEnumerable<string> SampleData {
            get
            {
                yield return "zh-CN";
                yield return "zh-HK";
                yield return "en-US";
            }
        }
        #endregion

        #region Commands
        public ICommand DownloadCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return SelectedLanguage != null; },
                    ExecuteCallback = delegate { StartDownload(); }
                };
            }
        }

        public ICommand CancleCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return client.IsBusy; },
                    ExecuteCallback = delegate { client.CancelAsync(); }
                };
            }
        }

        public ICommand DeleteCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return SelectedExistLanguage != null && GlobalSettings.Language != SelectedExistLanguage; },
                    ExecuteCallback = delegate
                    {
                        if (MessageBox.Show(Application.Current.FindResource<string>(ResourceKeys.IDS_NOTE_LANGUAGE_DELETE_CONFIRM_MESSAGE), Application.Current.FindResource<string>(ResourceKeys.IDS_NOTE_LANGUAGE_DELETE_CONFIRM_TITLE), MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                        {
                            DeleteLanguagePackage();
                        }
                    }
                };
            }
        }

        public ICommand SetLanguageCommand
        {
            get
            {
                return new GenericCommand()
                {
                    CanExecuteCallback = delegate { return SelectedExistLanguage != null; },
                    ExecuteCallback = delegate
                    {
                        GlobalSettings.Language = SelectedExistLanguage;
                        RaisePropertyChanged(() => GlobalSettings);
                    }
                };
            }
        }
        #endregion
    }
}
